/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Data;

import Gramaticas.lex3;
import Gramaticas.parser3;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Rey
 */
public class Generar3D {
    
    int temp;
    int etiq;
    String temporal;
    String etiqueta;
    String escribir;
    ArrayList<String> temporales;
    Tabla tablaSimbolos;
    ArrayList<Nodo3>  listaCodigoMetodos;
    ArrayList<String>  listaCodigoConsola;
    Nodo3 metodoPrincipal;
    boolean consola;
    boolean archivos;
    String direccion;
    String nombre;
    String salidacpp;

    public Generar3D() {
        
        this.temp=0;
        this.etiq=0;
        temporal ="t";
        temporales = new ArrayList<String>();
    }

    public Generar3D(Tabla tablaSimbolos) {
        this.tablaSimbolos = tablaSimbolos;
        this.temp=0;
        this.etiq=0;
        temporal ="t";
        temporales = new ArrayList<String>();
        this.listaCodigoConsola = new ArrayList<String>();
        this.listaCodigoMetodos = new ArrayList<Nodo3>();
    }
    
    
    
    public void GenTemp()
    {
        temp++;
        temporal = "t"+String.valueOf(temp);
        if(!temporales.contains(temporal))
        {
            temporales.add(temporal);
        }
        
    }
    
    public void ResetTemp()
    {
        temp =0;
        temporal ="t";
    }
    
    public String getTemporal() {
        return temporal;
    }    

    public void GenEti()
    {
        etiq++;
        etiqueta = "L"+String.valueOf(etiq);
    }

    public int getTemp() {
        return temp;
    }

    public void setTemp(int temp) {
        this.temp = temp;
    }    

    public int getEtiq() {
        return etiq;
    }

    public void setEtiq(int etiq) {
        this.etiq = etiq;
    }

    public String getEtiqueta() {
        return etiqueta;
    }   

    public Tabla getTablaSimbolos() {
        return tablaSimbolos;
    }

    public void setTablaSimbolos(Tabla tablaSimbolos) {
        this.tablaSimbolos = tablaSimbolos;
    }

    public ArrayList<String> getTemporales() {
        return temporales;
    }

    public void setTemporales(ArrayList<String> temporales) {
        this.temporales = temporales;
    }

    public ArrayList<Nodo3> getListaCodigoMetodos() {
        return listaCodigoMetodos;
    }

    public void setListaCodigoMetodos(ArrayList<Nodo3> listaCodigoMetodos) {
        this.listaCodigoMetodos = listaCodigoMetodos;
    }

    public ArrayList<String> getListaCodigoConsola() {
        return listaCodigoConsola;
    }

    public void setListaCodigoConsola(ArrayList<String> listaCodigoConsola) {
        this.listaCodigoConsola = listaCodigoConsola;
    }

    public Nodo3 getMetodoPrincipal() {
        return metodoPrincipal;
    }

    public void setMetodoPrincipal(Nodo3 metodoPrincipal) {
        this.metodoPrincipal = metodoPrincipal;
    }

    public boolean isConsola() {
        return consola;
    }

    public void setConsola(boolean consola) {
        this.consola = consola;
    }

    public String getDireccion() {
        return direccion;
    }

    public void setDireccion(String direccion) {
        this.direccion = direccion;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
        this.salidacpp = nombre.replace(".SI",".cpp");
    }

    public boolean isArchivos() {
        return archivos;
    }

    public void setArchivos(boolean archivos) {
        this.archivos = archivos;
    }
    
    
    
    public Nodo3 generarChar3D(Token val)
    {
        String valor = val.getLexema();
        valor = valor.replace("_", "");
        valor = cambiarCaracteresEscape(valor);
        char caracter = valor.charAt(0);
        int codigo = (int)caracter;
        String nuevoValor = String.valueOf(codigo);
        Nodo3 nodo3 = new Nodo3(nuevoValor);
        nodo3.setTipo(Tipos.CARACTER);
        return nodo3;
    }
    
    public Nodo3 generarCadena3D(Token val)
    {
        String valor = val.getLexema();
        valor = valor.replace("\\", "");
        valor = cambiarCaracteresEscape(valor);
        char letras[] = valor.toCharArray();            
        GenTemp();
        escribir = temporal + " =  h;\n"; //valor inicial del heap
        String temp1 = temporal;
        
        for(int i =0; i < letras.length; i++) //guardando los valores de la cadena en el heap
        {
            GenTemp();
            escribir = escribir + temporal +" = "+ temp1 +" + "+String.valueOf(i)+";\n";
            escribir = escribir + "heap[(int)"+temporal+"] = "+ ((int)letras[i])+";\n";
        }
        
        //agregando fin de cadena al heap
        GenTemp();
        escribir = escribir + temporal +" = "+ temp1 +" + "+letras.length+";\n";
        escribir = escribir + "heap[(int)"+temporal+"] = 0;\n";
        
        //reservamos memoria
        escribir = escribir + "h = h + "+(letras.length+1)+";\n";
        
        Nodo3 nodo3 = new Nodo3(escribir, temp1, Tipos.CADENA);
        return nodo3;
        
    }
    
    public String cambiarCaracteresEscape(String cadena)
    {
        String cadena2;
        cadena2 = cadena;
        cadena2 = cadena2.replace(":s", "\n");
        cadena2 = cadena2.replace(":\\", "\\");
        cadena2 = cadena2.replace(":_", "_");
        cadena2 = cadena2.replace(":t", "\t");
        cadena2 = cadena2.replace(":r", "\r");       
        return cadena2;
    }
    
    public Nodo3 generarValorId3D(Token val, String ambito)
    {
        Simbolo variable = tablaSimbolos.obtenerSimbolo(ambito, val);
        String valor ="";
        escribir = "";
        String tipo ="";
        Nodo3 nodo3;
        
        if(variable!= null)//verificamos que exista la variable
        {
            if(variable.getRol().compareTo(Tipos.PARAMETRO)==0)//verificamos si es un parametro
            {
                if(variable.getReferencia().compareTo(Tipos.REF)==0)//verificamos si es un parametro por referencia
                {
                    String temp1;
                    GenTemp();
                    escribir = escribir + temporal + " = p + "+variable.getPosicion()+";\n"; //posicion de la variable
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +  temporal +" = pila[(int)"+temp1+"];\n"; //valor del puntero 
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +  temporal +" = pila[(int)"+temp1+"];\n"; //valor de la variable 
                    nodo3 = new Nodo3(escribir, temporal, variable.getTipo());
                    nodo3.setEfn(Tipos.VAR);
                    return nodo3; 
                    
                    
                }
                else
                {
                    GenTemp();
                    escribir = escribir + temporal + " = p + "+variable.getPosicion()+";\n"; //posicion de la variable
                    String temp1 = temporal;
                    GenTemp();
                    escribir = escribir +  temporal +" = pila[(int)"+temp1+"];\n"; //valor de la variable
                    nodo3 = new Nodo3(escribir, temporal, variable.getTipo());
                    nodo3.setEfn(Tipos.VAR);
                    return nodo3; 
                }
            }
            else // es una variable
            {
                if(variable.getTipoVariable()==Tipos.LOCAL) //verificamos si es una variable local
                {                       
                    
                        GenTemp();
                        escribir = escribir + temporal + " = p + "+variable.getPosicion()+";\n"; //posicion de la variable
                        String temp1 = temporal;
                        GenTemp();
                        escribir = escribir +  temporal +" = pila[(int)"+temp1+"];\n";
                        nodo3 = new Nodo3(escribir, temporal, variable.getTipo());
                        nodo3.setEfn(Tipos.VAR);
                        return nodo3;                        
                    
                    
                }
                else // es una variable de clase
                {
                    GenTemp();
                    String temp1;
                    escribir = escribir + temporal + " = p + 0;\n"; //posicion del this
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n"; // posicion de la variable
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir + temporal + " = "+temp1+" + "+variable.getPosicion()+";\n"; // posicion de la variable
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir + temporal + " = heap[(int)"+temp1+"];\n";//valor de la variable
                    nodo3 = new Nodo3(escribir, temporal,variable.getTipo());
                    nodo3.setEfn(Tipos.VAR);
                    return nodo3;
                }
                
            }
        }
        
        nodo3 = new Nodo3(escribir, valor, tipo);
        return nodo3;
    }
    
    public Nodo3 generarOperacion3D(Object e1,String op,Object e2)
    {
              escribir = "";
              Nodo3 n1 = (Nodo3)e1;
              Nodo3 n2 = (Nodo3)e2;
              Nodo3 nodo3;
              
              if(op.compareTo("+")==0)
              {
                  if(n1.getTipo().compareTo(Tipos.CADENA)==0 || n2.getTipo().compareTo(Tipos.CADENA)==0)
                  {
                                            
                      if(n1.getTipo().compareTo(Tipos.CADENA)==0 && n2.getTipo().compareTo(Tipos.CADENA)==0) //cadenas nada mas
                      {                                   
                          
                          return  generarConcatenar3D(n1, n2);                          
                      }
                      else if(n1.getTipo().compareTo(Tipos.CADENA)==0 && n2.getTipo().compareTo(Tipos.CARACTER)==0) //cadenas nada mas
                      {                                   
                          Nodo3 nod = agregarCharHeap(n2);
                          return  generarConcatenar3D(n1, nod);                          
                      }
                      else if(n1.getTipo().compareTo(Tipos.CARACTER)==0 && n2.getTipo().compareTo(Tipos.CADENA)==0) //cadenas nada mas
                      {                                   
                          Nodo3 nod = agregarCharHeap(n1);
                          return  generarConcatenar3D(nod, n2);                          
                      }
                      else 
                      {
                          nodo3 = new Nodo3("");
                          return nodo3;
                      }
                  }
                  else 
                  {
                      escribir = n1.getCad()+n2.getCad();
                      GenTemp();
                      escribir = escribir + temporal + " = " + n1.getValor() +" "+ op+" "+ n2.getValor()+";\n";
                      String tipo = tipoOperacionAritmetica(n1.getTipo(), n2.getTipo());
                      nodo3 = new Nodo3(escribir, temporal,tipo);
                      return nodo3;
                  }
              }
              else if(op.compareTo("%")==0)
              {
                  escribir = n1.getCad()+n2.getCad();
                  GenTemp();
                  escribir = escribir + temporal + " = (int)" + n1.getValor() +" "+ op+" (int)"+ n2.getValor()+";\n";
                  String tipo = tipoOperacionAritmetica(n1.getTipo(), n2.getTipo());
                  nodo3 = new Nodo3(escribir, temporal,tipo);
                  return nodo3;
              }
              else
              {
                  escribir = n1.getCad()+n2.getCad();
                  GenTemp();
                  escribir = escribir + temporal + " = " + n1.getValor() +" "+ op+" "+ n2.getValor()+";\n";
                  String tipo = tipoOperacionAritmetica(n1.getTipo(), n2.getTipo());
                  nodo3 = new Nodo3(escribir, temporal,tipo);
                  return nodo3;
              }
              
              

    }
    
    public Nodo3 agregarCharHeap(Nodo3 e1)
    {
         escribir = e1.getCad();
         GenTemp();
         escribir = escribir + temporal +" =  h;\n";         
         escribir = escribir + "heap[(int)"+temporal+"] = "+e1.getValor()+";\n";
         String temp1 = temporal;
         GenTemp();
         escribir = escribir + temporal +" = "+temp1+ " + 1;\n";
         escribir = escribir + "heap[(int)"+temporal+"] = 0;\n";
         escribir = escribir + "h = h + 2;\n";
         Nodo3 nodo = new Nodo3(escribir,temporal, Tipos.CADENA);
         return nodo;
    }
    
    public Nodo3 generarConcatenar3D(Nodo3 n1, Nodo3 n2)
    {
          Nodo3 nodo3;
          String posicionHeap;
          String temporal1;
          String temporalh1;
          String temporalv1;
          String etiret;
          String etiv;
          String temp1;
          
          escribir = n1.getCad() + n2.getCad();
          GenTemp();
          escribir = escribir + temporal +" = h;\n"; //asignamos la posicion actual del heap
          posicionHeap = temporal; //guardamos el temporal con la posicion del heap
          GenTemp();
          temporalh1 = temporal;
          escribir = escribir +temporalh1 +" = "+posicionHeap+";\n"; //temporal para movernos en el heap para crear la nueva cadena
          GenTemp();
          temporal1 = temporal;
          escribir = escribir +temporal1 + " = "+n1.getValor()+";\n"; //temporal que contiene el puntero del heap del primer valor
          GenEti();
          etiret = etiqueta;
          escribir = escribir + etiret +":\n";
          GenTemp();
          temporalv1 = temporal;
          escribir = escribir + temporalv1 + " = heap[(int)"+temporal1+"];\n"; //temporal que guarda el contenido del heap
          GenEti();
          etiv =etiqueta;   
          GenEti();
          escribir = escribir + "if ( "+temporalv1+" != 0 ) goto "+etiv+";\ngoto "+etiqueta+";\n";
          escribir = escribir +etiv+":\n";                          
          escribir = escribir + "heap[(int)"+temporalh1+"] = "+temporalv1+";\n"; //hacemos la copia del valor del heap
          escribir = escribir + temporalh1 +" = "+temporalh1+" + 1;\n";  //nos movemos una posicion
          escribir = escribir + temporal1 +" = "+temporal1+" + 1;\n";   //nos movemos una posicion
          escribir = escribir + "h = h + 1;\ngoto "+etiret+";\n"+etiqueta+":\n";

          GenTemp();
          escribir = escribir + temporal +" = h;\n"; //asignamos la posicion actual del heap
          temp1 = temporal; //guardamos el temporal con la posicion del heap
          GenTemp();
          temporalh1 = temporal;
          escribir = escribir +temporalh1 +" = "+temp1+";\n"; //temporal para movernos en el heap para crear la nueva cadena
          GenTemp();
          temporal1 = temporal;
          escribir = escribir +temporal1 + " = "+n2.getValor()+";\n"; //temporal que contiene el puntero del heap del primer valor
          GenEti();
          etiret = etiqueta;
          escribir = escribir + etiret +":\n";
          GenTemp();
          temporalv1 = temporal;
          escribir = escribir + temporalv1 + " = heap[(int)"+temporal1+"];\n"; //temporal que guarda el contenido del heap
          GenEti();
          etiv =etiqueta;   
          GenEti();
          escribir = escribir + "if ( "+temporalv1+" != 0 ) goto "+etiv+";\ngoto "+etiqueta+";\n";
          escribir = escribir +etiv+":\n";                          
          escribir = escribir + "heap[(int)"+temporalh1+"] = "+temporalv1+";\n"; //hacemos la copia del valor del heap
          escribir = escribir + temporalh1 +" = "+temporalh1+" + 1;\n";  //nos movemos una posicion
          escribir = escribir + temporal1 +" = "+temporal1+" + 1;\n";   //nos movemos una posicion
          escribir = escribir + "h = h + 1;\ngoto "+etiret+";\n"+etiqueta+":\n";

          GenTemp();
          escribir = escribir + temporal+ " = h;\n";
          escribir = escribir + "heap[(int)"+temporal+"] = 0;\n"; //agregamos el final de cadena
          escribir = escribir + "h = h + 1;\n";

          nodo3 = new Nodo3(escribir, posicionHeap, Tipos.CADENA);
          return nodo3;
    }
    
    public String tipoOperacionAritmetica(String e1,String e2)
    {
        

        if(e1.compareTo(Tipos.DECIMAL)==0 && e2.compareTo(Tipos.DECIMAL)==0)
        {
            return Tipos.DECIMAL;
        }
        else if(e1.compareTo(Tipos.DECIMAL)==0 && e2.compareTo(Tipos.ENTERO)==0)
        {
            return Tipos.DECIMAL;
        }
        else if(e1.compareTo(Tipos.ENTERO)==0 && e2.compareTo(Tipos.DECIMAL)==0)
        {
            return Tipos.DECIMAL;
        }
        else if(e1.compareTo(Tipos.ENTERO)==0 && e2.compareTo(Tipos.ENTERO)==0)
        {
            return Tipos.ENTERO;
        }
        else
        {
            return Tipos.ERRORTIPO;
        }
    }
    
    public Nodo3 generarLogicos3D(Object e1,String op,Object e2)
    {
              escribir = "";
              String eV;
              String eF;
              Nodo3 n1 = (Nodo3)e1;
              Nodo3 n2 = (Nodo3)e2;
              Nodo3 nodo3;
              escribir = n1.getCad()+n2.getCad();
              GenEti();
              eV = etiqueta;
              GenEti();
              eF = etiqueta;
              escribir = escribir + "if ( "+ n1.getValor()+" " +op+" "+ n2.getValor() +" ) goto "+eV+";\ngoto "+eF+";\n";
              nodo3 = new Nodo3(escribir,"",Tipos.BOOLEANO);
              nodo3.setEv(eV);
              nodo3.setEf(eF);
              return nodo3;

    }
    
    public Nodo3 generarAnd3D(Object e1,Object e2)
    {
        escribir = "";
        Nodo3 n1 = (Nodo3)e1;
        Nodo3 n2 = (Nodo3)e2;
        Nodo3 nodo3;         
        
        escribir =  n1.getCad()+"\n";
        escribir =  escribir + n1.getEv() +":\n";
        escribir =  escribir + n2.getCad();
        nodo3 = new Nodo3(escribir,"",n2.getEv(),n1.getEf()+":\n"+n2.getEf());
        return nodo3;
    }
    
    public Nodo3 generarOr3D(Object e1, Object e2)
    {
        escribir ="";
        Nodo3 n1 = (Nodo3)e1;
        Nodo3 n2 = (Nodo3)e2;
        Nodo3 nodo3;
        escribir = n1.getCad() + "\n";
        escribir = escribir + n1.getEf()+":\n";
        escribir = escribir + n2.getCad();
        nodo3 = new Nodo3(escribir,"",n1.getEv()+":\n"+n2.getEv(),n2.getEf());
        return nodo3;
        
    }
    
    public Nodo3 generarIf3D(Object cnd, Object crp)
    {
        escribir ="";
        Nodo3 nodo3;
        Nodo3  cond = (Nodo3)cnd;
        Nodo3  cuerpo = (Nodo3)crp;
        
        escribir = cond.getCad();
	escribir = escribir + cond.getEv() + ":\n";
	escribir = escribir + cuerpo.getCad();
        nodo3 = new Nodo3(escribir,"","",cond.getEf());        
        return nodo3;
    }
    
    public Nodo3 generarElseIf3D(Object lis, Object sei)
    {
        escribir ="";
        Nodo3  n1 = (Nodo3)lis;
        Nodo3  n2 = (Nodo3)sei;        
        escribir = n1.getCad() + "\n";
	escribir = escribir + "goto "+n1.getEfn()+ ";\n";
	escribir = escribir + n1.getEf()+":\n";
        escribir = escribir + n2.getCad();
        n1.setCad(escribir);
        n1.setEf(n2.getEf());
        	
        
        
        
        return n1;
    }
    
    public Nodo3 generarSentenciaIf3D(Object sif, Object sef)
    {
        escribir ="";
        Nodo3 nodo3;
        Nodo3  n1 = (Nodo3)sif;
        Nodo3  n2 = (Nodo3)sef;
        
																					
        escribir = n1.getCad();
        if(n2.getEfn().length()==0)
        {
            GenEti();
            escribir = escribir + "goto "+etiqueta+";\n";
            escribir = escribir + n1.getEf()+":\n";
            escribir = escribir + n2.getCad();
            escribir = escribir +etiqueta+":\n";
        }
        else
        {
            escribir = escribir + "goto "+n2.getEfn()+";\n";
            escribir = escribir + n1.getEf()+":\n";
            escribir = escribir + n2.getCad();
            
            if(n2.getEf().length()>0)
            {
                escribir = escribir + n2.getEf()+":\n";
            }
            
            escribir = escribir + n2.getEfn()+":\n";
        }
        
        
        nodo3 = new Nodo3(escribir,"");
        return nodo3;

    }
    
    public Nodo3 generarWhile3D(String eti,Object cnd, Object crp )
    {
        escribir ="";
        String etq;
        Nodo3 nodo3;

        etq = eti;
        
        
        Nodo3 cond = (Nodo3) cnd;
        Nodo3 cuerpo = (Nodo3) crp;
        
        escribir = etq + ":\n";
        escribir = escribir + cond.getCad() + "\n";
        escribir = escribir + cond.getEv() + ":\n";
        escribir = escribir + cuerpo.getCad() + "\n";
        escribir = escribir + "goto " +etq+ ";\n";
        escribir = escribir + cond.getEf() + ":\n";
        escribir = escribir.replace("Lbreak", cond.getEf());
        nodo3 = new Nodo3(escribir,"");        
        return nodo3;
        
        
    }
    
    public Nodo3 generarFor3D(String eti,Object asi, Object cnd, Object aum, Object var, String ambito , Object crp)
    {
        escribir ="";
        Nodo3 nodo3;
        Nodo3  asig = (Nodo3)asi;
        Nodo3  cond = (Nodo3)cnd;
        String  ope = aum.toString();
        Token variable = (Token)var;
        Nodo3  cuerpo = (Nodo3)crp;

        String etq = eti;
        escribir = asig.getCad() + "\n";
        escribir = escribir + etq +":\n";    //escribimos la etiqueta retorno    
        
        escribir = escribir + cond.getCad() + "\n";   //las sentencias del expresion
        escribir = escribir + cond.getEv() + ":\n";    //escribimos la etiqueta de verdadero      
        escribir = escribir + cuerpo.getCad() + "\n";  //escribimos el cuerpo del ciclo
        String escribirtemp = escribir;
        
        //aumento
        Nodo3 aumento = generarPosicionVariable(var, ambito);
        escribir = escribirtemp;
        escribir = escribir + aumento.getCad();
        escribirtemp = escribir;
        Nodo3 inc = generarValorId3D((Token)var, ambito);
        escribir = escribirtemp;
        escribir = escribir + inc.getCad();
        GenTemp();
        escribir = escribir + temporal + " = "+ inc.getValor()+";\n";
        String temp1 = temporal;
        GenTemp();
        escribir = escribir + temporal + " = "+temp1+" "+aum.toString()+" 1;\n";
        escribir = escribir + aumento.getTipo() + " = "+ temporal+";\n";        
        
        escribir = escribir + "goto " + etq + ";\n"; //regresamos a la etiqueta retorno      
       
        escribir = escribir + cond.getEf() + ":\n"; // escribimos la etiqueta falsa de la condicion
        
        
        escribir = escribir.replace("Lbreak", cond.getEf()); // remplazamos las etiquetas de break por la etiqueta falsa
        nodo3 = new Nodo3(escribir,"");
        
        return nodo3;
						
    }
    
    public Nodo3 generarSwitch3D(Nodo3 sw, ArrayList<Nodo3> cases, Object def)
    {
        escribir = "";
        Nodo3 nodo3;
        Nodo3 swit = sw;
        Nodo3 defa = (Nodo3)def;
        GenEti();
        String etq = etiqueta;
        escribir = swit.getCad()+"\n";
        
        for(Nodo3 cas : cases)
        {
            escribir = escribir + "if ( " + swit.getValor() + " != " + cas.getValor() + " )  goto " + cas.getEv() + ";\n";
            escribir = escribir + cas.getCad() + "\n";
            if(!cas.getEf().equals(""))
            {
               escribir = escribir + "goto " + etq + ";\n"; 
            }
            escribir = escribir +cas.getEv()+ " :\n";
            
            
        }
	
        escribir = escribir + defa.getCad() +"\n";
        
        if(!defa.getEf().equals(""))
        {
           escribir = escribir + "goto " + etq + ";\n"; 
        }
        escribir = escribir.replace("Lbreak", etq);
        escribir = escribir + etq +" :\n";
        System.out.println(escribir);
        nodo3 = new Nodo3(escribir,"");
        
        return nodo3;
        
						  
    }
    
    public ArrayList<Nodo3> generarPosicionVariables(Object variables, String ambito)
    {
        ArrayList<Token> listaVariables = (ArrayList<Token>)variables;
        ArrayList<Nodo3> listaPosiciones = new ArrayList<Nodo3>();
        
        Simbolo sim;
        
            for(Token variable :listaVariables) 
            {
                sim = tablaSimbolos.obtenerSimbolo(ambito, variable);
                
                if(sim!=null)
                {
                    if(sim.getReferencia()!=null && sim.getReferencia().compareTo(Tipos.REF)==0  )//si es un parametro por referencia
                    {
                        String temp1;
                        GenTemp();
                        escribir = temporal +" = p + "+sim.getPosicion(); // posicion del parametro
                        temp1 = temporal;
                        GenTemp();
                        escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n"; //posicion del puntero
                        String val = "pila[(int)"+temporal+"]";
                        Nodo3 nodo = new Nodo3(escribir, temporal,val);
                        listaPosiciones.add(nodo);
                    }
                    else // si es una variable
                    {
                        if(sim.getTipoVariable() == Tipos.LOCAL) //si es una variable local
                        {
                            GenTemp();
                            escribir = temporal +" = p + "+ sim.getPosicion()+";\n";
                            String val = "pila[(int)"+temporal+"]";
                            Nodo3 nodo = new Nodo3(escribir, temporal,val);
                            listaPosiciones.add(nodo);
                        }
                        else // es una variable de clase
                        {
                            String temp1;
                            GenTemp();
                            escribir = temporal +" = p + 0;\n"; // posicion del this
                            temp1 = temporal;
                            GenTemp();
                            escribir = escribir + temporal + " = pila[(int)"+temp1+ "];\n";
                            temp1 = temporal;
                            GenTemp();
                            escribir = escribir + temporal + " = "+temp1+ " + "+sim.getPosicion()+";\n";
                            String val = "heap[(int)"+temporal+"]";
                            Nodo3 nodo = new Nodo3(escribir, temporal,val);
                            listaPosiciones.add(nodo);
                                    
                        }
                    }
                }
            }
        
        return listaPosiciones;
        
    }
    
    public Nodo3 generarPosicionVariable(Object var, String ambito)
    {
               
        Simbolo sim;        
        Token variable = (Token)var;            
        sim = tablaSimbolos.obtenerSimbolo(ambito, variable);

        if(sim!=null)
        {
            if(sim.getReferencia()!=null && sim.getReferencia().compareTo(Tipos.REF)==0  )//si es un parametro por referencia
            {
                String temp1;
                GenTemp();
                escribir = temporal +" = p + "+sim.getPosicion(); // posicion del parametro
                temp1 = temporal;
                GenTemp();
                escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n"; //posicion del puntero
                String val = "pila[(int)"+temporal+"]";
                Nodo3 nodo = new Nodo3(escribir, temporal,val);
                nodo.setEfn(sim.getTipo());
                return nodo;
            }
            else // si es una variable
            {
                if(sim.getTipoVariable() == Tipos.LOCAL) //si es una variable local
                {
                    GenTemp();
                    escribir = temporal +" = p + "+ sim.getPosicion()+";\n";
                    String val = "pila[(int)"+temporal+"]";
                    Nodo3 nodo = new Nodo3(escribir, temporal,val);
                    nodo.setEfn(sim.getTipo());
                    return nodo;
                }
                else // es una variable de clase
                {
                    String temp1;
                    GenTemp();
                    escribir = temporal +" = p + 0;\n"; // posicion del this
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir + temporal + " = pila[(int)"+temp1+ "];\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir + temporal + " = "+temp1+ " + "+sim.getPosicion()+";\n";
                    String val = "heap[(int)"+temporal+"]";
                    Nodo3 nodo = new Nodo3(escribir, temporal,val);
                    nodo.setEfn(sim.getTipo());
                    return nodo;

                }
            }
        }
        else
        {
            
            return new Nodo3("");
        }
            
        
       
        
    }
        
    public Nodo3 generarAsignacionVariables(ArrayList<Nodo3> posiciones, Object exp)
    {
        escribir = "";
        Nodo3 expresion = (Nodo3)exp;
        
        if(expresion.getTipo().compareTo(Tipos.LLAMADA)==0)
        {
            escribir = expresion.getCad();
            
            for(Nodo3 nodo : posiciones)
            {
                escribir = escribir + nodo.getCad();
                escribir = escribir + nodo.getTipo() +" = "+ expresion.getValor()+";\n";
            }
            
            Nodo3 nodo = new Nodo3(escribir,"");
            return nodo;
        }
        else
        {
            for(Nodo3 nodo : posiciones)
            {
                escribir = escribir + nodo.getCad();
            }

            escribir = escribir + expresion.getCad();

            for(Nodo3 nodo : posiciones)
            {
                escribir = escribir + nodo.getTipo() +" = "+ expresion.getValor()+";\n";
            }
            
            Nodo3 nodo = new Nodo3(escribir,"");
            return nodo;
        }
        
    }
    
    public Nodo3 generarAsignacionVariable(Nodo3 posicion, Object exp)
    {
        escribir = "";
        Nodo3 expresion = (Nodo3)exp;
        
        if(expresion.getTipo().compareTo(Tipos.LLAMADA)==0)
        {
            escribir = expresion.getCad() + posicion.getCad();
            escribir = escribir + posicion.getTipo() +" = "+ expresion.getValor()+";\n";  
            Nodo3 nodo = new Nodo3(escribir,"");
            return nodo;
        }
        else
        {
            
            escribir = escribir + posicion.getCad();
            escribir = escribir + expresion.getCad();
            escribir = escribir + posicion.getTipo() +" = "+ expresion.getValor()+";\n";            
            Nodo3 nodo = new Nodo3(escribir,"");
            return nodo;
        }
        
    }
    
    public Nodo3 generarAsignacionArreglo(Token variable, String ambito, Nodo3 posicion, Object exp)
    {
        escribir = "";
        Nodo3 expresion = (Nodo3)exp;
        
        Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito, variable);
        
        if(sim!=null)
        {
            if(expresion.getTipo().compareTo(Tipos.LLAMADA)==0)
            {
                
                escribir = escribir + expresion.getCad();
                escribir = escribir + posicion.getCad();
                
                if(sim.getTipoVariable()==Tipos.LOCAL)
                {
                    escribir = escribir + "pila[(int)"+posicion.getValor()+"] = "+ expresion.getValor()+";\n"; 
                }
                else
                {
                    escribir = escribir + "heap[(int)"+posicion.getValor()+"] = "+ expresion.getValor()+";\n"; 
                }
                
                Nodo3 nodo = new Nodo3(escribir,"");
                return nodo;
            }
            else
            {

                escribir = escribir + posicion.getCad();
                escribir = escribir + expresion.getCad();
                
                if(sim.getTipoVariable()==Tipos.LOCAL)
                {
                    escribir = escribir + "pila[(int)"+posicion.getValor()+"] = "+ expresion.getValor()+";\n"; 
                }
                else
                {
                    escribir = escribir + "heap[(int)"+posicion.getValor()+"] = "+ expresion.getValor()+";\n"; 
                }
                
                Nodo3 nodo = new Nodo3(escribir,"");
                return nodo;
            }
        }
        else
        {
            return new Nodo3("");
        }
        
    }
        
    public Nodo3 generarRetorno3D(Object expr)
    {
        Nodo3 expresion = (Nodo3)expr;
        Nodo3 nodo3;
        escribir = expresion.getCad();
        GenTemp();
        escribir = escribir + temporal + " = p + 0;\n";
        escribir = escribir + "pila[(int)"+temporal+"] = "+expresion.getValor()+";\n";
        escribir = escribir + "goto Lfin;\n";
        nodo3 = new Nodo3(escribir,"");
        return nodo3;
        
    }
    
    public Nodo3 generarPosicionObjeto(Object obj, Object var, String ambito)
    {
         Token objeto = (Token)obj;
         Token variable = (Token)var;
         Nodo3 posObjeto = generarPosicionVariable(objeto, ambito);
         
         if(posObjeto!=null)
         {
             
             String nuevoAmbito = posObjeto.getEfn()+"_"+variable.getLexema();
             Simbolo sim = tablaSimbolos.obtenerSimbolo(nuevoAmbito, variable);
             
             if(sim!=null)
             {
                 escribir = posObjeto.getCad();
                 GenTemp();
                 escribir = escribir + temporal +" = "+posObjeto.getValor()+" + "+ sim.getPosicion()+";\n";
                 String valor = "heap[(int)"+temporal+"]";
                 Nodo3 nodo = new Nodo3(escribir, temporal, valor);
                 return nodo;
             }
             else
             {
                 return new Nodo3("");
             }
         }
         else
         {
             return new Nodo3("");
         }
         
         
    }
    
    public Nodo3 generarValorObjeto(Object obj, Object var, String ambito)
    {
         Token objeto = (Token)obj;
         Token variable = (Token)var;
         Nodo3 posObjeto = generarPosicionVariable(objeto, ambito);
         
         if(posObjeto!=null)
         {
             Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito,objeto);
             
             if(sim!= null)
             {
                 String nuevoAmbito = sim.getTipo()+"_"+variable.getLexema();
                 
                 Simbolo simclas = tablaSimbolos.obtenerSimbolo(nuevoAmbito, variable);
                 
                 if(simclas!=null)
                 {
                     escribir = posObjeto.getCad();
                     GenTemp();
                     escribir = escribir + temporal +" = "+posObjeto.getValor()+" + "+ simclas.getPosicion()+";\n";
                     String temp1 = temporal;
                     GenTemp();
                     escribir = escribir + temporal +" = heap[(int)"+temp1+"];\n";
                     Nodo3 nodo = new Nodo3(escribir, temporal, simclas.getTipo());
                     return nodo;
                 }
                 else
                 {
                     return new Nodo3("");
                 }
             }
             else
             {
                 return new Nodo3("");
             }

         
             
             
         }
         else
         {
             return new Nodo3("");
         }
         
         
    }
       
    public Nodo3 generarAccesoArreglos(Object array,String ambito, Object cadena,  Object exp, int dimension)
    {
         Token variable = (Token)array;
         Nodo3 dimen = (Nodo3)cadena;
         Nodo3 expresion = (Nodo3)exp;
         
         Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito, variable);
         
         if(sim!=null)
         {
             
             
                 if(dimension==0)
                 {
                     Nodo3 posicionArreglo = generarPosicionVariable(variable, ambito);
                     escribir = posicionArreglo.getCad() + expresion.getCad();
                     GenTemp();
                     escribir = escribir + temporal + " = "+ posicionArreglo.getValor() +" + "+expresion.getValor()+";\n";
                     Nodo3 nodo = new Nodo3(escribir, temporal);
                     return nodo;
                 }
                 else
                 {
                     String temp1;
                     escribir = dimen.getCad();//dimension anterior
                     GenTemp();
                     escribir = escribir + expresion.getCad();
                     escribir = escribir + temporal + " = " + dimen.getValor() + " * "+tamañoDimension(sim.getTam_dimensiones(), dimension)+";\n";
                     temp1 = temporal;
                     GenTemp();
                     escribir = escribir + temporal + " = " + temp1 + " + " + expresion.getValor()+";\n";
                     Nodo3 nodo = new Nodo3(escribir,temporal);
                     return nodo;



                 }
             
             
             
         }
         else
         {
             return new Nodo3("");
         }
         
    }
    
    
    public String tamañoDimension(String dimensiones, int dim)
    {
        String dims []= dimensiones.split(",");
        String dimActual = dims[dim];
        return dimActual; 
    }
    
    public Nodo3 generarValorArreglos(String ambito, Token variable, Object dim, int opcion)
    {
        Nodo3 dimensiones = (Nodo3)dim;
        
        Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito, variable);
        
        if(opcion ==1 )
        {
            if(sim!=null)
            {
                if(sim.getTipoVariable()==Tipos.LOCAL)
                {
                    escribir = dimensiones.getCad();
                    GenTemp();
                    escribir =  escribir +temporal+" = pila[(int)"+dimensiones.getValor()+"];\n";
                    Nodo3 nodo = new Nodo3(escribir, temporal, sim.getTipo());
                    return nodo;
                }
                else
                {
                    escribir = dimensiones.getCad();
                    GenTemp();
                    escribir =  escribir +temporal+" = heap[(int)"+dimensiones.getValor()+"];\n";
                    Nodo3 nodo = new Nodo3(escribir, temporal, sim.getTipo());
                    return nodo;
                }
            }
            else
            {
                return new Nodo3("");
            }
        }
        else
        {
            if(sim!=null)
            {
                if(sim.getTipoVariable()==Tipos.LOCAL)
                {
                    escribir = dimensiones.getCad();
                    Nodo3 nodo = new Nodo3(escribir, temporal, sim.getTipo());
                    return nodo;
                }
                else
                {
                    escribir = dimensiones.getCad();
                    Nodo3 nodo = new Nodo3(escribir, temporal, sim.getTipo());
                    return nodo;
                }
            }
            else
            {
                return new Nodo3("");
            }
            
        }
        
       
    }
    
    public Nodo3 generarNuevoObjeto(Object var, Object con, String ambito)
    {
        Token variable = (Token)var;
        Token clase = (Token)con;
        
        Nodo3 posicionVar = generarPosicionVariable(variable, ambito);
        
        if(posicionVar!=null)
        {
            Simbolo sim = tablaSimbolos.obtenerSimbolo(clase.getLexema());
            
            if(sim!=null)
            {
                escribir = posicionVar.getCad();
                GenTemp();
                escribir = escribir + temporal + " = h;\n"; // posicion del puntero
                escribir = escribir + "h = h + "+sim.getTamaño()+";\n"; //reservamos memoria
                escribir = escribir + "pila[(int)"+posicionVar.getValor()+"] = "+temporal+";\n"; //asignamos el valor de la memoria
                String temp1 = temporal;
                
                Simbolo ambitoActual = tablaSimbolos.obtenerSimbolo(ambito);
                
                if(ambitoActual!=null)
                {
                    GenTemp();
                    escribir = escribir + temporal +" = p + "+ambitoActual.getTamaño()+";\n";
                    String temp2 = temporal;
                    GenTemp();
                    escribir = escribir + temporal + " = "+temp2 + " + 0;\n";
                    escribir = escribir + "pila[(int)"+temporal+"] = "+ temp1+";\n";
                    Nodo3 nodo = new Nodo3(escribir, temp2,String.valueOf(ambitoActual.getTamaño()));
                    return nodo;
                }
                else
                {
                    return new Nodo3("");
                }
                
            }
            else
            {
                return new Nodo3("");
            }
        }
        else
        {
            return new Nodo3("");
        }
        
    }
    
    public Nodo3 generarNuevoObjeto(Object puntero, Object var, Object con, String ambito)
    {
        Token variable = (Token)var;
        Token clase = (Token)con;
        
        Nodo3 posicionVar = generarPosicionObjeto(puntero, var, ambito);
        
        if(posicionVar!=null)
        {
            Simbolo sim = tablaSimbolos.obtenerSimbolo(clase.getLexema());
            
            if(sim!=null)
            {
                escribir = posicionVar.getCad();
                GenTemp();
                escribir = escribir + temporal + " = h;\n"; // posicion del puntero
                escribir = escribir + "h = h + "+sim.getTamaño()+";\n"; //reservamos memoria
                escribir = escribir + posicionVar.getTipo()+" = "+temporal+";\n"; //asignamos el valor de la memoria
                String temp1 = temporal;
                
                Simbolo ambitoActual = tablaSimbolos.obtenerSimbolo(ambito);
                
                if(ambitoActual!=null)
                {
                    GenTemp();
                    escribir = escribir + temporal +" = p + "+ambitoActual.getTamaño()+";\n";
                    String temp2 = temporal;
                    GenTemp();
                    escribir = escribir + temporal + " = "+temp2 + " + 0;\n";
                    escribir = escribir + "pila[(int)"+temporal+"] = "+ temp1+";\n";
                    Nodo3 nodo = new Nodo3(escribir, temp2,String.valueOf(ambitoActual.getTamaño()));
                    return nodo;
                }
                else
                {
                    return new Nodo3("");
                }
                
            }
            else
            {
                return new Nodo3("");
            }
        }
        else
        {
            return new Nodo3("");
        }
        
    }
    
    
    public Nodo3 generarLLamadaNuevoObjeto(Nodo3 nodo, String llamada)
    {
        escribir = nodo.getCad();
        escribir = escribir + "p = p + "+ nodo.getTipo()+";\n";
        escribir = escribir + llamada +"();\n";
        escribir = escribir + "p = p - "+ nodo.getTipo()+";\n";
        Nodo3 nodo3 = new Nodo3(escribir,"");
        return nodo3;
    }
    
    public Nodo3 generarPreparacionLLamada(Object funcion, String ambito )
    {
        
        String temp1,temp2;
        if( funcion instanceof Token)
        {
            Nodo3 nodo = generarPosicionVariable(funcion, ambito);
            
            if(nodo!=null)
            {
                escribir = nodo.getCad();
                GenTemp();
                escribir = escribir + temporal + " = "+nodo.getTipo()+";\n";
                temp1 = temporal;
                Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);

                if(sim!=null)
                {
                    GenTemp();
                    escribir = escribir + temporal + " = p + "+sim.getTamaño()+";\n";
                    temp2 = temporal;
                    GenTemp();
                    escribir = escribir + temporal + " = "+temp2 +" + 0;\n";
                    escribir = escribir + "pila[(int)"+temporal+"] = "+ temp1+";\n";
                    Nodo3 nodo3 = new Nodo3(escribir, temp2);
                    return nodo3;
                }
                else
                {
                    return new Nodo3("");
                }
                
            }
        }
        else
        {
            GenTemp();                    
            escribir = temporal + " = p + 0;\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n";
            temp1 = temporal;
            Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);
            
            if(sim!=null)
            {
                GenTemp();
                escribir = escribir + temporal + " = p + "+sim.getTamaño()+";\n";
                temp2 = temporal;
                GenTemp();
                escribir = escribir + temporal + " = "+temp2 +" + 0;\n";
                escribir = escribir + "pila[(int)"+temporal+"] = "+ temp1+";\n";
                Nodo3 nodo = new Nodo3(escribir, temp1);
                return nodo;
            }
            else
            {
                return new Nodo3("");
            }
        }
        
        
        return new Nodo3("");
    }
    
    public Nodo3 generarPasoParametros(Nodo3 prep, int par)
    {
        escribir = prep.getCad();
        GenTemp();
        escribir = escribir + temporal + " = "+prep.getValor()+" + "+par+";\n";
        Nodo3 nodo = new Nodo3(escribir, temporal);
        return nodo;
        
    }
    
    public Nodo3 generarValorParametro(Nodo3 par, Nodo3 exp)
    {
        escribir = par.getCad() + exp.getCad();
        escribir = escribir + "pila[(int)"+par.getValor()+"] = "+exp.getValor()+";\n";
        Nodo3 nodo = new Nodo3(escribir,"",exp.getTipo());
        
        if(exp.getTipo().compareTo(Tipos.LLAMADA)==0)
        {
            nodo.setEfn(exp.getEfn());
        }
        else
        {
            nodo.setEfn(exp.getTipo());
        }
        
        return nodo;
    }
    
    public Nodo3 generarLlamada(Object ambitoSuperior, Object func, String ambito, String parametros, Nodo3 cadena)
    {
        String nombr;
        Simbolo sim;
        Simbolo amb;
        Nodo3 nodo;
        String tipo;
        String temp1;
        
        
        if(ambitoSuperior instanceof Token)
        {
            Simbolo padre = tablaSimbolos.obtenerSimbolo(ambito, (Token)ambitoSuperior);
            Token fun = (Token)func;
            
            if(padre!=null)
            {
                if(cadena.getEfn().compareTo("")==0)
                {
                    nombr = padre.getTipo()+"_"+fun.getLexema();
                }
                else
                {
                    nombr = padre.getTipo()+"_"+fun.getLexema()+"_"+cadena.getEfn();
                }
                
            }
            else
            {
                if(cadena.getEfn().compareTo("")==0)
                {
                    nombr = fun.getLexema();
                }
                else
                {
                    nombr = fun.getLexema()+"_"+cadena.getEfn();
                }
                
            }
                    
        }
        else
        {
                
                if(func instanceof Token)
                {
                    Token fun = (Token)func;
                    nombr = ambitoSuperior.toString()+"_"+fun.getLexema()+"_"+cadena.getEfn();
                }
                else
                {
                    if(cadena.getEfn().compareTo("")==0)
                    {
                        nombr = ambitoSuperior.toString();
                    }
                    else
                    {
                        nombr = ambitoSuperior.toString()+"_"+cadena.getEfn();
                    }
                }
            
        }
        
        
        
        sim = tablaSimbolos.obtenerSimbolo(nombr);
        
        if(sim!=null)
        {
            amb = tablaSimbolos.obtenerSimbolo(ambito);
            
            if(amb!=null)
            {
                escribir = cadena.getCad();
                escribir = escribir + "p = p + "+amb.getTamaño()+";\n";
                escribir = escribir + nombr + "();\n";
                escribir = escribir + "p = p - "+amb.getTamaño()+";\n";
                tipo = sim.getTipo();
                
                if(tipo.compareTo(Tipos.NORMAL)!=0 && tipo.compareTo(Tipos.CONSTRUCTOR)!=0)
                {
                    GenTemp();
                    escribir = escribir + temporal+ " =  p + "+amb.getTamaño()+";\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir + temporal+ " = pila[(int)"+temp1+"];\n";
                    nodo = new Nodo3(escribir,temporal,Tipos.LLAMADA);
                    nodo.setEfn(tipo);
                    return nodo;
                }
                else
                {
                    nodo = new Nodo3(escribir,"", tipo);
                    return nodo;
                }
                
            }
            else
            {
                return new Nodo3("");
            }
        }
        else
        {
            return  null;
        }
        
    }
    
    public Nodo3 generarMetodo(String nombre, Object crp)
    {
        Nodo3 cuerpo = (Nodo3)crp;
        
        if(nombre.compareTo("principal")==0)
        {
            escribir = "int main(){\n";
            escribir = escribir + cuerpo.getCad()+"\n";
            escribir = escribir +"return 0;\n}\n";
        }
        else
        {
            escribir = "void "+nombre+"(){\n";
            escribir = escribir + cuerpo.getCad()+"\n";
            escribir = escribir +"Lfin:\ntx=0;\n}\n";
        }
        Nodo3 nodo = new Nodo3(escribir, "");
        return nodo;                
    }
    
    public Nodo3 generarPrepararImprimir(String ambito)
    {
        Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);
        
        if(sim!=null)
        {
            String temp1;
            GenTemp();
            escribir = temporal + " =  p + "+sim.getTamaño()+";\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal + " = " + temp1 + " + 0;\n";
            Nodo3 nodo = new Nodo3(escribir, temporal,String.valueOf(sim.getTamaño()));
            return nodo;
            
        }
        else
        {
            return new Nodo3("");
        }
    }
    
    public Nodo3 generarMetodoImprimir(Nodo3 met, Object exp)
    {
        Nodo3 expresion = (Nodo3)exp;
        escribir = met.getCad() + expresion.getCad();
        escribir = escribir + "pila[(int)"+met.getValor()+"] = "+expresion.getValor()+";\n";
        escribir = escribir + "p = p + "+met.getTipo()+";\n";
        
        if(expresion.getTipo().compareTo(Tipos.NORMAL)!=0)
        {
            if(expresion.getTipo().compareTo(Tipos.LLAMADA)==0)
            {
                escribir = escribir +"imprimir_"+expresion.getEfn()+"();\n";
            }
            else if(expresion.getTipo().compareTo(Tipos.BOOLEANO)==0)
            {
                escribir = escribir +"imprimir_booleano();\n";
            }
            else
            {
                escribir = escribir +"imprimir_"+expresion.getTipo()+"();\n";
            }
        }
        
        escribir = escribir + "p = p - "+met.getTipo()+";\n";
        Nodo3 nodo = new Nodo3(escribir,"");
        return nodo;
    }
    
    public Nodo3 generarLlamadasCasteos(Object a , Object de, String ambito)
    {
        String tipo = a.toString();
        Nodo3  expresion = (Nodo3)de;
        
        if(tipo.compareTo(Tipos.ENTERO)==0)
        {
            if(expresion.getTipo().compareTo(Tipos.DECIMAL)==0)
            {
                Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);
                
                if(sim!=null)
                {
                    String temp1;
                    GenTemp();
                    escribir = escribir + expresion.getCad();
                    escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = "+temp1+" + 1;\n";
                    escribir = escribir + "pila[(int)"+temporal+"] = "+expresion.getValor()+";\n";
                    escribir = escribir + "p = p + "+sim.getTamaño()+";\n";
                    escribir = escribir + "castear_entero_decimal();\n";
                    escribir = escribir + "p = p - "+sim.getTamaño()+";\n";
                    GenTemp();
                    escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = "+temp1+" + 0;\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = pila[(int)"+temp1+"];\n";
                    Nodo3 nodo = new Nodo3(escribir, temporal,Tipos.ENTERO);
                    generarMetodoCasteo("castear_entero_decimal",Tipos.ENTERO);
                    return nodo;
                    
                }
            }
            else if(expresion.getTipo().compareTo(Tipos.LLAMADA)==0)
            {
                 if(expresion.getEfn().compareTo(Tipos.DECIMAL)==0)
                 {
                     Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);
                
                     if(sim!=null)
                     {
                        String temp1;
                        GenTemp();
                        escribir = escribir + expresion.getCad();
                        escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                        temp1 = temporal;
                        GenTemp();
                        escribir = escribir +temporal +" = "+temp1+" + 1;\n";
                        escribir = escribir + "pila[(int)"+temporal+"] = "+expresion.getValor()+";\n";
                        escribir = escribir + "p = p + "+sim.getTamaño()+";\n";
                        escribir = escribir + "castear_entero_decimal();\n";
                        escribir = escribir + "p = p - "+sim.getTamaño()+";\n";
                        GenTemp();
                        escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                        temp1 = temporal;
                        GenTemp();
                        escribir = escribir +temporal +" = "+temp1+" + 0;\n";
                        temp1 = temporal;
                        GenTemp();
                        escribir = escribir +temporal +" = pila[(int)"+temp1+"];\n";
                        Nodo3 nodo = new Nodo3(escribir, temporal,Tipos.ENTERO);
                        generarMetodoCasteo("castear_entero_decimal",Tipos.ENTERO);
                        return nodo;

                     }
                     
                 }
                
            }
        
            
        }
        else if(tipo.compareTo(Tipos.DECIMAL)==0)
        {
            if(expresion.getTipo().compareTo(Tipos.ENTERO)==0)
            {
                Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);
                
                if(sim!=null)
                {
                    String temp1;
                    GenTemp();
                    escribir = escribir + expresion.getCad();
                    escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = "+temp1+" + 1;\n";
                    escribir = escribir + "pila[(int)"+temporal+"] = "+expresion.getValor()+";\n";
                    escribir = escribir + "p = p + "+sim.getTamaño()+";\n";
                    escribir = escribir + "castear_decimal_entero();\n";
                    escribir = escribir + "p = p - "+sim.getTamaño()+";\n";
                    GenTemp();
                    escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = "+temp1+" + 0;\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = pila[(int)"+temp1+"];\n";
                    Nodo3 nodo = new Nodo3(escribir, temporal,Tipos.DECIMAL);
                    generarMetodoCasteo("castear_decimal_entero",Tipos.DECIMAL);
                    return nodo;
                    
                }
            }
            else if(expresion.getTipo().compareTo(Tipos.LLAMADA)==0)
            {
                 if(expresion.getEfn().compareTo(Tipos.ENTERO)==0)
                 {
                     Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);
                
                     if(sim!=null)
                     {
                        String temp1;
                        GenTemp();
                        escribir = escribir + expresion.getCad();
                        escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                        temp1 = temporal;
                        GenTemp();
                        escribir = escribir +temporal +" = "+temp1+" + 1;\n";
                        escribir = escribir + "pila[(int)"+temporal+"] = "+expresion.getValor()+";\n";
                        escribir = escribir + "p = p + "+sim.getTamaño()+";\n";
                        escribir = escribir + "castear_decimal_entero();\n";
                        escribir = escribir + "p = p - "+sim.getTamaño()+";\n";
                        GenTemp();
                        escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                        temp1 = temporal;
                        GenTemp();
                        escribir = escribir +temporal +" = "+temp1+" + 0;\n";
                        temp1 = temporal;
                        GenTemp();
                        escribir = escribir +temporal +" = pila[(int)"+temp1+"];\n";
                        Nodo3 nodo = new Nodo3(escribir, temporal,Tipos.DECIMAL);
                        generarMetodoCasteo("castear_decimal_entero",Tipos.DECIMAL);
                        return nodo;

                     }
                     
                 }
                
            }
        
            
        }
        else if(tipo.compareTo(Tipos.CADENA)==0)
        {
            if(expresion.getTipo().compareTo(Tipos.CADENA)!=0 && expresion.getTipo().compareTo(Tipos.NORMAL)!=0 && expresion.getTipo().compareTo(Tipos.CONSTRUCTOR)!=0)
            {
                Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);
                
                if(sim!=null)
                {
                    String temp1;
                    GenTemp();
                    escribir = escribir + expresion.getCad();
                    escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = "+temp1+" + 1;\n";
                    escribir = escribir + "pila[(int)"+temporal+"] = "+expresion.getValor()+";\n";
                    escribir = escribir + "p = p + "+sim.getTamaño()+";\n";
                    escribir = escribir + "castear_cadena_"+expresion.getTipo()+"();\n";
                    escribir = escribir + "p = p - "+sim.getTamaño()+";\n";
                    GenTemp();
                    escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = "+temp1+" + 0;\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = pila[(int)"+temp1+"];\n";
                    Nodo3 nodo = new Nodo3(escribir, temporal,Tipos.CADENA);
                    generarMetodoCasteoCadena("castear_cadena_"+expresion.getTipo(),expresion.getTipo());
                    return nodo;
                    
                }
            }
            else if(expresion.getTipo().compareTo(Tipos.LLAMADA)==0)
            {
                 Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);
                
                if(sim!=null)
                {
                    String temp1;
                    GenTemp();
                    escribir = escribir + expresion.getCad();
                    escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = "+temp1+" + 1;\n";
                    escribir = escribir + "pila[(int)"+temporal+"] = "+expresion.getValor()+";\n";
                    escribir = escribir + "p = p + "+sim.getTamaño()+";\n";
                    escribir = escribir + "castear_cadena_"+expresion.getTipo()+"();\n";
                    escribir = escribir + "p = p - "+sim.getTamaño()+";\n";
                    GenTemp();
                    escribir = temporal + " = p + "+sim.getTamaño()+";\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = "+temp1+" + 0;\n";
                    temp1 = temporal;
                    GenTemp();
                    escribir = escribir +temporal +" = pila[(int)"+temp1+"];\n";
                    Nodo3 nodo = new Nodo3(escribir, temporal,Tipos.CADENA);
                    generarMetodoCasteoCadena("castear_cadena_"+expresion.getTipo(),expresion.getTipo());
                    return nodo;
                    
                }
                
            }
        
            
        }
        
        
        return new Nodo3("");
    }
    
    public void generarMetodoCasteo(String nombre, String tipo)
    {
        
        if(tipo.compareTo(Tipos.ENTERO)==0)
        {
            escribir = "void "+nombre+"(){\n";
            String temp1;
            GenTemp();
            escribir = escribir + temporal + " = p + 1";
            temp1 = temporal;
            GenTemp();
            escribir = escribir +  temporal +" = pila[(int)"+temp1+"];\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir +  temporal +" = (int)"+temp1+";\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal + " = p + 0";
            escribir = escribir + "pila[(int)"+temporal+"] = "+temp1+";\n";
            Nodo3 nodo = new Nodo3(escribir,"");
            agregarCodigoMetodos(nodo);
        }
        else if(tipo.compareTo(Tipos.DECIMAL)==0)
        {
            escribir = "void "+nombre+"(){\n";
            String temp1;
            GenTemp();
            escribir = escribir + temporal + " = p + 1";
            temp1 = temporal;
            GenTemp();
            escribir = escribir +  temporal +" = pila[(int)"+temp1+"];\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir +  temporal +" = (float)"+temp1+";\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal + " = p + 0";
            escribir = escribir + "pila[(int)"+temporal+"] = "+temp1+";\n";
            Nodo3 nodo = new Nodo3(escribir,"");
            agregarCodigoMetodos(nodo);
            
        }
        
    }
    
    public void generarMetodoCasteoCadena(String nombre, String tipo) {
        
        escribir = "void "+ escribir +"(){\nLfin:\tx=0;\n}\n";
        Nodo3 nodo = new Nodo3(escribir,"");
        agregarCodigoMetodos(nodo);
    }
    
    public Nodo3 generarMetodoCrearArchivo(int opc)
    {
        String temp1;
        String eti1;
        String etini;
        
        if(opc == 1)
        {
            escribir = "void escribir_cadena_cadena(){\nchar nombre[128];\n";
        }
        else
        {
            escribir = "void agregar_cadena_cadena(){\nchar nombre[128];\n";
        }
        
        GenTemp();
        escribir = escribir + temporal + " = p + 0; \n";
        temp1 = temporal;
        GenTemp();
        escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n";
        GenEti();
        etini = etiqueta;
        escribir = escribir + etiqueta +":\n";
        temp1 = temporal;
        GenTemp();
        escribir = escribir + temporal +" = heap[(int)"+temp1+"];\n";
        GenEti();
        escribir = escribir + "if ("+temporal+" != 0) goto "+etiqueta+";\n";
        eti1 = etiqueta;
        GenEti();
        escribir = escribir + "goto "+etiqueta+";\n";
        escribir = escribir + eti1+":\n";
        escribir = escribir + "nombre[(int)"+temp1+"]=(char)"+temporal+";\n";
        escribir = escribir + temp1 + " = "+ temp1 + " + 1;\n";
        escribir = escribir + "goto "+etini+";\n";
        escribir = escribir + etiqueta+":\n";
        escribir = escribir + temp1 + " = "+ temp1 + " + 1;\n";
        escribir = escribir + "nombre[(int)"+temp1+"]=0;\n";
        escribir = escribir +"std::ofstream ofs (nombre, std::ofstream::app);\n";
        
        GenTemp();
        escribir = escribir + temporal + " = p + 1; \n";
        temp1 = temporal;
        GenTemp();
        escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n";
        GenEti();
        etini = etiqueta;
        escribir = escribir + etiqueta +":\n";
        temp1 = temporal;
        GenTemp();
        escribir = escribir + temporal +" = heap[(int)"+temp1+"];\n";
        GenEti();
        escribir = escribir + "if ("+temporal+" != 0) goto "+etiqueta+";\n";
        eti1 = etiqueta;
        GenEti();
        escribir = escribir + "goto "+etiqueta+";\n";
        escribir = escribir + eti1+":\n";
        escribir = escribir + "ofs << (char)"+temporal+";\n";
        escribir = escribir + temp1 + " = "+ temp1 + " + 1;\n";
        escribir = escribir + "goto "+etini+";\n";
        escribir = escribir + etiqueta+":\nLfin:\nofs.close();\ntx=0;\n}\n";
        
        Nodo3 nodo = new Nodo3(escribir,"");
        return nodo;
    }
    
    public Nodo3 genearMetodoLLamadaArchivos(Nodo3 nombre, Nodo3 cadena, String ambito, int opc)
    {
        
         escribir = nombre.getCad()+cadena.getCad();
         
         Simbolo sim = tablaSimbolos.obtenerSimbolo(ambito);
         
         if(sim!=null)
         {
             String temp1;
             GenTemp();
             escribir = escribir+ temporal + " = p + "+sim.getTamaño()+";\n";
             temp1 = temporal;
             GenTemp();
             escribir = escribir +  temporal + " = "+temp1+ " + 0;\n";
             escribir = escribir + "pila[(int)"+temporal+"] = "+nombre.getValor()+";\n";
             
             GenTemp();
             escribir = escribir+ temporal + " = p + "+sim.getTamaño()+";\n";
             temp1 = temporal;
             GenTemp();
             escribir = escribir +  temporal + " = "+temp1+ " + 1;\n";
             escribir = escribir + "pila[(int)"+temporal+"] = "+cadena.getValor()+";\n";
             escribir = escribir +"p = p + "+sim.getTamaño()+";\n";
             if(opc == 1)
             {
                escribir = escribir + "escribir_cadena_cadena();\n";
             }
             else
             {
                escribir = escribir + "agregar_cadena_cadena();\n";
             }
             escribir = escribir +"p = p - "+sim.getTamaño()+";\n"; 
             
             Nodo3 nodo = new Nodo3(escribir, "");
             
                          
             return nodo;
             
             
         }
         else
         {
             return new Nodo3("");
         }
         
    }
    
    public void generarImprimir3D()
    {
        
            
       
            String temp1;
            String eti1;
            String etini;
            Nodo3 nodo;
            escribir = "void imprimir_cadena(){\n";
            GenTemp();
            escribir = escribir + temporal + " = p + 0;\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n";
            GenEti();
            etini = etiqueta;
            escribir = escribir + etiqueta +":\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal +" = heap[(int)"+temp1+"];\n";
            GenEti();
            escribir = escribir + "if ("+temporal+" != 0) goto "+etiqueta+";\n";
            eti1 = etiqueta;
            GenEti();
            escribir = escribir + "goto "+etiqueta+";\n";
            escribir = escribir + eti1+":\n";
            escribir = escribir + "cout<<(char)"+temporal+";\n";
            escribir = escribir + temp1 + " = "+ temp1 + " + 1;\n";
            escribir = escribir + "goto "+etini+";\n";
            escribir = escribir + etiqueta+":\nLfin:\ntx=0;\n}\n";
            nodo = new Nodo3(escribir, "");
            listaCodigoMetodos.add(nodo);
            
            
            
        
            escribir = "void imprimir_entero(){\n";
            GenTemp();
            escribir = escribir + temporal + " = p + 0;\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n";
            escribir = escribir +"cout<<(int)"+temporal+";\n";
            escribir = escribir + "}\n";
            nodo = new Nodo3(escribir, "");
            listaCodigoMetodos.add(nodo);
        
        
            
            escribir = "void imprimir_booleano(){\n";
            GenTemp();
            escribir = escribir + temporal + " = p + 0;\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n";
            escribir = escribir +"cout<<(int)"+temporal+";\n";
            escribir = escribir + "}\n";
            nodo = new Nodo3(escribir, "");
            listaCodigoMetodos.add(nodo); 
        
            escribir = "void imprimir_decimal(){\n";
            GenTemp();
            escribir = escribir + temporal + " = p + 0;\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n";
            escribir = escribir +"cout<<"+temporal+";\n";
            escribir = escribir + "}\n";
            listaCodigoConsola.add(escribir);
        
            escribir = "void imprimir_caracter(){\n";
            GenTemp();
            escribir = escribir + temporal + " = p + 0;\n";
            temp1 = temporal;
            GenTemp();
            escribir = escribir + temporal + " = pila[(int)"+temp1+"];\n";
            escribir = escribir +"cout<<(char)"+temporal+";\n";
            escribir = escribir + "}\n";
            nodo = new Nodo3(escribir, "");
            listaCodigoMetodos.add(nodo);
        
            
    }
    
    public void agregarCodigoMetodos(Nodo3 nodo)
    {
        listaCodigoMetodos.add(nodo);
    }
    
    public void agregarMain(Nodo3 nodo)
    {
        metodoPrincipal = nodo;
    }
    
    public void agregarCodigoImports(Token importe)
    {
        String direccionImporte = importe.getLexema().replace("\"","");
        File arch = tablaSimbolos.listaImports.get(direccionImporte);
        
        if(arch!=null)
        {
            try {
                parser3 parsergenerar3d;
                parsergenerar3d = new parser3(new lex3(new FileInputStream(arch)));
                parsergenerar3d.agregarTablaSimbolos(tablaSimbolos);
                parsergenerar3d.parse();
                temporales.addAll(parsergenerar3d.c3d.getTemporales());
                temp = parsergenerar3d.c3d.getTemp();
                etiq = parsergenerar3d.c3d.getEtiq();
                consola =  parsergenerar3d.c3d.isConsola();
                listaCodigoMetodos.addAll(parsergenerar3d.c3d.getListaCodigoMetodos());
            } catch (FileNotFoundException ex) {
                Logger.getLogger(Generar3D.class.getName()).log(Level.SEVERE, null, ex);
            } catch (Exception ex) {
                Logger.getLogger(Generar3D.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        
        
    }
    
    public void escribirArchivo(String path, String cadena, boolean append) {
        File archivo = new File(path);
        BufferedWriter salida = null;
        try 
        {
            salida = new BufferedWriter(new FileWriter(archivo, append));
        } 
        catch (Exception ex) 
        {
           
        }
        try 
        {
            salida.write("\r\n"+cadena);

            if (salida != null) {
                salida.flush();
                salida.close();
            }
        } 
        catch (IOException ex) 
        {
           
        }
    }
    
    
    public void escribirTemporales()
    {
        String salida = direccion+salidacpp;
        escribir = "#include <iostream>\n#include <fstream>\n\nusing namespace std;\n\nfloat pila[10000];\nfloat heap[10000];\nint p=0;\nint h=0;\n";
        escribirArchivo(salida,escribir,false);
        
        
        
        
            for(String temp1 : temporales)
            {
                escribir = "float "+temp1+";";
                escribirArchivo(salida,escribir,true);
            }
            
            escribir = "float tx;";
            escribirArchivo(salida,escribir,true);
            
        
        
        for(Nodo3 nod : listaCodigoMetodos)
        {
            escribirArchivo(salida,nod.getCad(),true);
        }
        
        if(metodoPrincipal!=null)
        {
            escribirArchivo(salida,metodoPrincipal.getCad(),true);
        }
    
    }

    
    
    
    
}
